JS References VS Copying

References - Strings, numbers and booleans:

    
     //Numbers
    let age = 100;
    let age2 = age;
    console.log(age, age2);
    // 100 100
    age = 200
    // 200 100
    
    // Strings
    let name = 'Wes';
    let name2 = name;
    console.log(name, name2);
    // Wes Wes
    name = 'Wesley';
    // Wes Wesley
    

Arrays


    // Consider this Array: 
    const players = ['Wes','Sarah','Ryan','Poppy'];
    

Creating an Array Reference:


    const team = players;
    console.log(players, team);
    // ["Wes","Sarah","Ryan","Poppy"]
    // ["Wes","Sarah","Ryan","Poppy"]

    // What if I update the team position array?
    team[3] = 'Lux'
    console.log(team);
    // ["Wes","Sarah","Ryan","Poppy"]

    // The original array:
    console.log(players);
    // ["Wes","Sarah","Ryan","Poppy"]

Copying an Array:


    // Copying with slice() 
    const team2 = players.slice();
    team2[3] = 'Lux';
    console.log(team2);
    // ["Wes","Sarah","Ryan","Lux"]

    // Copying with concat()
    const team3 = [].concat(players);
    // ["Wes","Sarah","Ryan","Poppy"]

    // Copying with ES6 Spread Operator '...'
    const team4 = [...players];
    team4[3] = 'heeeeeeee hawwwwwww';
    // ["Wes","Sarah","Ryan","heeeeeeee hawwwwwww"] 
    
    // Copying with Array.from() 
    const team5 = Array.from(players);
    team4[5] = 'cool';
    // ["Wes","Sarah","Ryan","cool"]

Objects

          
          // Considere this object
          const person = {
              name: 'Wes Bos',
              age: 80
          }

Creating a Reference:


    const captain = person;
    console.log(captain);
    // {"name": "Wes Bos", "age": 80, "number": 99}

Copying an Object:


    // Copying with Object.assign() 
    const cap2 = Object.assign({}, person,
      {number: 99, age: 12});
    console.log(cap2);
    // {"name": "Wes Bos", "age": 12, "number": 99}

Copying an Object using JSON.stringfy()


        // Considere this another object
        const wes = {
            name: 'Wes',
            age: 100,
            social: {
              name: '@wesbos',
              age: 'wesbos.developer',   
          }
        }

      const dev = Object.assign({}, wes);
      console.log(wes);
      /* {
        "name": "wes",
        "age": "100",
        "social": {
          "twitter": "@wesbos",
          "facebook": "wesbos.developer"
        }
      }*/
  
      //If we reassign one object property 
      //in the first level:
      dev.name = 'Wesley'
      console.log(dev);
      // It's ok! Works! 
      /*{
        "name": "Wesley",
        "age": "100",
        "social": {
          "twitter": "@wesbos",
          "facebook": "wesbos.developer"
        }
      }
        */
  
      // What if I try to reassign in 1 level deep?
      dev.social.twitter = '@coolman';
      console.log(dev.social);
      //{"twitter": "@coolman", "facebook": "wesbos.developer"}
  
      // Unfortunately this reassign the original object:
      console.log(wes.social);
      //{"twitter": "@coolman", "facebook": "wesbos.developer"}
  
      // I understand this happens because we copy 
      // just the first object level and form some 
      // reason not access the nested objects properties.
      // Another way suggested by Wes, 
      // but not recommended by him, 
      // is to transform this in JSON and parse the strings
      // to turn this strings in Object again 
  
      const dev2 = JSON.stringify(wes);
      console.log(dev2);
      // We just have the string, because the
      // JSON.stringify() transforms an object to string
      //{"name":"wes","age":"100","social":{"twitter":"@coolman","facebook":"wesbos.developer"}}
  
      // To transform this string in an object again
      // it's necessary to parse it:
      const dev3 = JSON.parse(JSON.stringify(wes));
      console.log(dev3);
      /* Now we have an object
      {
        "name": "wes",
        "age": "100",
        "social": {
          "twitter": "@coolman",
          "facebook": "wesbos.developer"
        }
      }*/
    
  
    dev3.social.twitter = '@coolman';
    console.log(dev3.social);
    // {
      "twitter": "@coolman",
      "facebook": "wesbos.developer"
    }
  
    //If we look in the original array:
    console.log(wes.social);
      /* The original array wasn't changed:
      {
        "twitter": "@wesbos",
        "facebook": "wesbos.developer"
      }*/